package com.example.snake;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * @author Jason
 * @PACKAGE_NAME com.example.snake
 * @Description 绘制窗体 绘制图形 绘制蛇的身体 动起来【窗口一直重绘，修改坐标】 控制方向【键盘监听事件，根据键盘方向】 食物【主体，位置】
 * @date 2023-12-07 16:04
 */
//继承Frame父类
public class SnackFrame06 extends Frame {
    /*移动距离*/
    private int moveDistance = 1; // 减少移动距离
    /*控制程序是否继续*/
    private boolean isRunning = true;
    //上1 下3 右0 左2
    private int direction = 0;
    //食物
    private Node food = new Node(randomNum(0, 600 / 20 - 1) * 20, randomNum(2, 500 / 20 - 1) * 20);//  /20是食物要和蛇平行

    /**
     * 蛇的主体部分
     */
    private Node[] body = {
            new Node(140, 100),
            new Node(120, 100),
            new Node(100, 100)
    };

    // 构造器中初始化窗体
    public SnackFrame06() {
        int width = 600;
        int height = 500;
        //设置距离显示器距离
        //        this.setLocation(200,100);
        //获取屏幕尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        //计算窗口左上角x坐标
        int x = (screenSize.width - width) / 2;
        //计算窗口左上角y坐标
        int y = (screenSize.height - height) / 2;
        //设置窗口位置
        this.setLocation(x, y);
        //设置窗口大小
        this.setSize(width, height);
        //设置背景色
        this.setBackground(Color.magenta);
        this.setTitle("贪吃蛇V1.0");
        //禁止改变窗体大小
        this.setResizable(false);
        //显示窗体
        this.setVisible(true);
        //添加窗口监听
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                //退出虚拟机
                System.exit(0);
            }
        });
        //监听键盘事件
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //上1 下3 右0 左2
                int dir = -1;
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP://向上走
                        dir = 1;
                        break;
                    case KeyEvent.VK_DOWN://向下走
                        dir = 3;
                        break;
                    case KeyEvent.VK_LEFT://向左走
                        dir = 2;
                        break;
                    case KeyEvent.VK_RIGHT://向右走
                        dir = 0;
                        break;
                }
                //根据合法性来修改方向（不允许在同一条线上修改）
                if (direction % 2 != dir % 2) {
                    direction = dir;
                }
                System.out.println("当前按键为:" + e.getKeyCode());
            }
        });
        start();
    }

    /**
     * 绘制窗体内容
     * 窗体显示 | 更新 自动调用
     *
     * @param g 画笔
     */
    @Override
    public void paint(Graphics g) {
        g.setColor(Color.ORANGE);
        for (int i = 0; i < body.length; i++) {
            //绘制蛇的主体部分
            body[i].drawNode(g, i);
        }

        g.setColor(Color.BLUE);
        food.drawNode(g, -1);
//        System.out.println("动起来");
    }

    /**
     * 随机产生食物
     */
    public void productFood() {
        food = new Node(randomNum(0, 600 / 20 - 1) * 20, randomNum(2, 500 / 20 - 1) * 20);//  /20是食物要和蛇平行
    }

    /**
     * 重绘窗体
     */
    public void start() {
        while (isRunning) {
            move();
            super.repaint();//手动让窗体重绘
            try {
                Thread.sleep(100);//间隔多长时间重绘一次
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 通过修改坐标达到移动效果
     */
    public void move() {
        /*向右移动*/
        /**
         *1. 每次给一个新的头节点，去掉尾节点
         * 2. 整体移动
         */
        Node[] temp = new Node[body.length];
        temp[0] = getNewHead();
        //拷贝数组 原数组，哪个地方开始拷贝，目标数组，目标数组的哪里，拷贝的长度
        System.arraycopy(body, 0, temp, 1, body.length - 1);
        this.body = temp;
    }

    /**
     * 根据方向确定新的头节点
     *
     * @return
     */
    public Node getNewHead() {
        Node newNode = body[0];
        //上1 下3 右0 左2
        switch (this.direction) {
            case 0://向右走
                newNode = new Node(newNode.getX() + 20, newNode.getY());
                break;
            case 2://向左走
                newNode = new Node(newNode.getX() - 20, newNode.getY());
                break;
            case 1://向上走
                newNode = new Node(newNode.getX(), newNode.getY() - 20);
                break;
            case 3://向下走
                newNode = new Node(newNode.getX(), newNode.getY() + 20);
                break;
        }
        return newNode;
    }

    /**
     * 根据min和=max随机生成食物
     *
     * @param min
     * @param max
     * @return
     */
    public static int randomNum(int min, int max) {
        return (int) (Math.random() * (max - min + 1) + min); //随机数范围[min,max]
    }

//    public static void main(String[] args) {
//        new SnackFrame06();
//    }
}
